package org.lib.ws;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

/**
 * 前后端交互的类实现消息的接收推送(自己发送给另一个人)
 * @author ben
 * @date 2021-11-12 21:00:25 CST
 */
@Component
@ServerEndpoint(value = "/ws3")
public class OneToOneWebSocket {

	private Consumer<Object> cs = System.out::println;
	
	/**
	 * 记录当前在线连接数
	 */
	private static AtomicInteger onlineCount = new AtomicInteger(0);
	
	/**
	 * 所有客户端
	 */
	private static Map<String, Session> clients = new ConcurrentHashMap<>(); 
	
	@OnOpen
	public void onOpen(Session session) {
		onlineCount.incrementAndGet();
		String sid = session.getId();
		clients.put(sid, session);
		cs.accept("onOpen: sid=" + sid + ", onlineCount=" + onlineCount + ", clients.size=" + clients.size());
	}
	
	@OnClose
	public void onClose(Session session) {
		onlineCount.decrementAndGet();
		String sid = session.getId();
		clients.remove(sid);
		cs.accept("onClose: sid=" + sid + ", onlineCount=" + onlineCount + ", clients.size=" + clients.size());
	}
	
	/**
	 * 收到客户端消息后调用的方法
	 * @author ben
	 * @date 2021-11-12 21:25:13 CST
	 * @param message JSON对象格式：{"id":id, "message":"info"}
	 * @param session
	 */
	@OnMessage
	public void onMessage(String message, Session session) {
		cs.accept("服务端收到客户端[" + session.getId() + "]的消息:" + message);
		
		try {
			JSONObject jobj = JSON.parseObject(message);
			String id = jobj.getString("id");
			String innerMessage = jobj.getString("message");
			
			if (id.equals(session.getId())) {
				cs.accept("warning：不能给自己发送消息");
				session.getBasicRemote().sendText("warning：不能给自己发送消息");
				return;
			}
			
			if (StringUtils.hasText(id) && StringUtils.hasText(message)) {
				Session tosession = clients.get(id);
				if (tosession != null) {
					tosession.getBasicRemote().sendText("id=" + id + " say:" + innerMessage);
				} else {
					cs.accept("warning: 用户已下线，无法接收消息");
					session.getBasicRemote().sendText("warning: 用户已下线，无法接收消息");
				}
			} else {
				cs.accept("id或message不能为空！请重新发送");
				session.getBasicRemote().sendText("id或message不能为空！请重新发送");
			}
		} catch (Exception e) {
			cs.accept("异常：解析失败，消息格式错误");
		}
	}
	
	@OnError
	public void onError(Session session, Throwable err) {
		cs.accept("发生错误：sid=" + session.getId() + ", e=" + err.getClass() + ", " + err.getMessage());
		err.printStackTrace();
	}
	
}
